View Javadoc

1   // x86ReferenceLinker.java, created Mon Feb  5 23:23:21 2001 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Compiler.Reference.x86;
5   
6   import joeq.Class.PrimordialClassLoader;
7   import joeq.Class.jq_Class;
8   import joeq.Class.jq_InstanceField;
9   import joeq.Class.jq_InstanceMethod;
10  import joeq.Class.jq_Method;
11  import joeq.Class.jq_Reference;
12  import joeq.Class.jq_StaticField;
13  import joeq.Class.jq_StaticMethod;
14  import joeq.Memory.Address;
15  import joeq.Memory.CodeAddress;
16  import joeq.Memory.HeapAddress;
17  import joeq.Memory.StackAddress;
18  import joeq.Runtime.SystemInterface;
19  import joeq.Runtime.Unsafe;
20  import jwutil.util.Assert;
21  
22  /***
23   * @author  John Whaley <jwhaley@alum.mit.edu>
24   * @version $Id: x86ReferenceLinker.java 1941 2004-09-30 03:37:06Z joewhaley $
25   */
26  public abstract class x86ReferenceLinker {
27  
28      public static /*final*/ boolean TRACE = false;
29      
30      static void patchCaller(jq_Method m, CodeAddress retloc) {
31          if (retloc.offset(-6).peek2() == (short)0xE890) {
32              // patch static call
33              retloc.offset(-4).poke4(m.getDefaultCompiledVersion().getEntrypoint().difference(retloc));
34          }
35          if (!m.isStatic() && ((jq_InstanceMethod)m).isVirtual()) {
36              ((Address[])m.getDeclaringClass().getVTable())[((jq_InstanceMethod)m).getOffset()>>2] = m.getDefaultCompiledVersion().getEntrypoint();
37          }
38      }
39      
40      static void getstatic4(jq_StaticField f) {
41          f = f.resolve1();
42          jq_Class k = f.getDeclaringClass();
43          k.cls_initialize();
44          CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
45          if (TRACE) SystemInterface.debugwriteln("backpatching getstatic4 "+f+" ip: "+retloc.stringRep());
46          int patchsize = x86ReferenceCompiler.patch_getstatic4(retloc, f);
47          // change our return address to reexecute patched region
48          StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
49      }
50      static void getstatic8(jq_StaticField f) {
51          f = f.resolve1();
52          jq_Class k = f.getDeclaringClass();
53          k.cls_initialize();
54          CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
55          if (TRACE) SystemInterface.debugwriteln("backpatching getstatic8 "+f+" ip: "+retloc.stringRep());
56          int patchsize = x86ReferenceCompiler.patch_getstatic8(retloc, f);
57          // change our return address to reexecute patched region
58          StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
59      }
60      static void putstatic4(jq_StaticField f) {
61          f = f.resolve1();
62          jq_Class k = f.getDeclaringClass();
63          k.cls_initialize();
64          CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
65          if (TRACE) SystemInterface.debugwriteln("backpatching putstatic4 "+f+" ip: "+retloc.stringRep());
66          int patchsize = x86ReferenceCompiler.patch_putstatic4(retloc, f);
67          // change our return address to reexecute patched region
68          StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
69      }
70      static void putstatic8(jq_StaticField f) {
71          f = f.resolve1();
72          jq_Class k = f.getDeclaringClass();
73          k.cls_initialize();
74          CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
75          if (TRACE) SystemInterface.debugwriteln("backpatching putstatic8 "+f+" ip: "+retloc.stringRep());
76          int patchsize = x86ReferenceCompiler.patch_putstatic8(retloc, f);
77          // change our return address to reexecute patched region
78          StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
79      }
80      static void getfield1(jq_InstanceField f) {
81          f = f.resolve1();
82          jq_Class k = f.getDeclaringClass();
83          Assert._assert(k.isClsInitialized());
84          CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
85          if (TRACE) SystemInterface.debugwriteln("backpatching getfield1 "+f+" ip: "+retloc.stringRep());
86          int patchsize = x86ReferenceCompiler.patch_getfield1(retloc, f);
87          // change our return address to reexecute patched region
88          StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
89      }
90      static void cgetfield(jq_InstanceField f) {
91          f = f.resolve1();
92          jq_Class k = f.getDeclaringClass();
93          Assert._assert(k.isClsInitialized());
94          CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
95          if (TRACE) SystemInterface.debugwriteln("backpatching cgetfield "+f+" ip: "+retloc.stringRep());
96          int patchsize = x86ReferenceCompiler.patch_cgetfield(retloc, f);
97          // change our return address to reexecute patched region
98          StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
99      }
100     static void sgetfield(jq_InstanceField f) {
101         f = f.resolve1();
102         jq_Class k = f.getDeclaringClass();
103         Assert._assert(k.isClsInitialized());
104         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
105         if (TRACE) SystemInterface.debugwriteln("backpatching sgetfield "+f+" ip: "+retloc.stringRep());
106         int patchsize = x86ReferenceCompiler.patch_sgetfield(retloc, f);
107         // change our return address to reexecute patched region
108         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
109     }
110     static void getfield4(jq_InstanceField f) {
111         f = f.resolve1();
112         jq_Class k = f.getDeclaringClass();
113         Assert._assert(k.isClsInitialized());
114         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
115         if (TRACE) SystemInterface.debugwriteln("backpatching getfield4 "+f+" ip: "+retloc.stringRep());
116         int patchsize = x86ReferenceCompiler.patch_getfield4(retloc, f);
117         // change our return address to reexecute patched region
118         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
119     }
120     static void getfield8(jq_InstanceField f) {
121         f = f.resolve1();
122         jq_Class k = f.getDeclaringClass();
123         Assert._assert(k.isClsInitialized());
124         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
125         if (TRACE) SystemInterface.debugwriteln("backpatching getfield8 "+f+" ip: "+retloc.stringRep());
126         int patchsize = x86ReferenceCompiler.patch_getfield8(retloc, f);
127         // change our return address to reexecute patched region
128         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
129     }
130     static void putfield1(jq_InstanceField f) {
131         f = f.resolve1();
132         jq_Class k = f.getDeclaringClass();
133         Assert._assert(k.isClsInitialized());
134         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
135         if (TRACE) SystemInterface.debugwriteln("backpatching putfield1 "+f+" ip: "+retloc.stringRep());
136         int patchsize = x86ReferenceCompiler.patch_putfield1(retloc, f);
137         // change our return address to reexecute patched region
138         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
139     }
140     static void putfield2(jq_InstanceField f) {
141         f = f.resolve1();
142         jq_Class k = f.getDeclaringClass();
143         Assert._assert(k.isClsInitialized());
144         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
145         if (TRACE) SystemInterface.debugwriteln("backpatching putfield2 "+f+" ip: "+retloc.stringRep());
146         int patchsize = x86ReferenceCompiler.patch_putfield2(retloc, f);
147         // change our return address to reexecute patched region
148         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
149     }
150     static void putfield4(jq_InstanceField f) {
151         f = f.resolve1();
152         jq_Class k = f.getDeclaringClass();
153         Assert._assert(k.isClsInitialized());
154         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
155         if (TRACE) SystemInterface.debugwriteln("backpatching putfield4 "+f+" ip: "+retloc.stringRep());
156         int patchsize = x86ReferenceCompiler.patch_putfield4(retloc, f);
157         // change our return address to reexecute patched region
158         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
159     }
160     static void putfield8(jq_InstanceField f) {
161         f = f.resolve1();
162         jq_Class k = f.getDeclaringClass();
163         Assert._assert(k.isClsInitialized());
164         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
165         if (TRACE) SystemInterface.debugwriteln("backpatching putfield8 "+f+" ip: "+retloc.stringRep());
166         int patchsize = x86ReferenceCompiler.patch_putfield8(retloc, f);
167         // change our return address to reexecute patched region
168         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
169     }
170     static void invokevirtual(jq_InstanceMethod f) {
171         f = f.resolve1();
172         jq_Class k = f.getDeclaringClass();
173         Assert._assert(k.isClsInitialized());
174         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
175         if (TRACE) SystemInterface.debugwriteln("backpatching invokevirtual "+f+" ip: "+retloc.stringRep());
176         int patchsize = x86ReferenceCompiler.patch_invokevirtual(retloc, f);
177         // change our return address to reexecute patched region
178         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
179     }
180     static void invokestatic(jq_Method f) {
181         f = (jq_Method)f.resolve();
182         jq_Class k = f.getDeclaringClass();
183         k.cls_initialize();
184         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
185         if (TRACE) SystemInterface.debugwriteln("backpatching invokestatic "+f+" ip: "+retloc.stringRep());
186         int patchsize = x86ReferenceCompiler.patch_invokestatic(retloc, f);
187         // change our return address to reexecute patched region
188         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
189     }
190     static void invokespecial(jq_InstanceMethod f) {
191         f = f.resolve1();
192         jq_Class k = f.getDeclaringClass();
193         k.cls_initialize();
194         f = jq_Class.getInvokespecialTarget(k, f);
195         CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
196         if (TRACE) SystemInterface.debugwriteln("backpatching invokespecial "+f+" ip: "+retloc.stringRep());
197         // special invocation is now directly bound.
198         int patchsize = x86ReferenceCompiler.patch_invokestatic(retloc, f);
199         // change our return address to reexecute patched region
200         StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
201     }
202     static long invokeinterface(jq_InstanceMethod f) throws Throwable {
203         f = f.resolve1();
204         int n_paramwords = f.getParamWords();
205         StackAddress obj_location = (StackAddress) StackAddress.getBasePointer().offset((n_paramwords+2)<<2);
206         Object o = ((HeapAddress) obj_location.peek()).asObject();
207         jq_Reference t = jq_Reference.getTypeOf(o);
208         if (!t.implementsInterface(f.getDeclaringClass()))
209             throw new IncompatibleClassChangeError(t+" does not implement interface "+f.getDeclaringClass());
210         jq_InstanceMethod m = t.getVirtualMethod(f.getNameAndDesc());
211         if (m == null)
212             throw new AbstractMethodError();
213         //if (TRACE) SystemInterface.debugwriteln("invokeinterface "+f+" on object type "+t+" resolved to "+m);
214         jq_Class k = m.getDeclaringClass();
215         k.cls_initialize();
216         for (int i=0; i<n_paramwords; ++i) {
217             int v = StackAddress.getBasePointer().offset((n_paramwords-i+2)<<2).peek4();
218             Unsafe.pushArg(v);
219         }
220         return Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
221     }
222     
223     public static final jq_Class _class;
224     public static final jq_StaticMethod _getstatic4;
225     public static final jq_StaticMethod _getstatic8;
226     public static final jq_StaticMethod _putstatic4;
227     public static final jq_StaticMethod _putstatic8;
228     public static final jq_StaticMethod _getfield1;
229     public static final jq_StaticMethod _cgetfield;
230     public static final jq_StaticMethod _sgetfield;
231     public static final jq_StaticMethod _getfield4;
232     public static final jq_StaticMethod _getfield8;
233     public static final jq_StaticMethod _putfield1;
234     public static final jq_StaticMethod _putfield2;
235     public static final jq_StaticMethod _putfield4;
236     public static final jq_StaticMethod _putfield8;
237     public static final jq_StaticMethod _invokevirtual;
238     public static final jq_StaticMethod _invokestatic;
239     public static final jq_StaticMethod _invokespecial;
240     public static final jq_StaticMethod _invokeinterface;
241     static {
242         _class = (jq_Class)PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Compiler/Reference/x86/x86ReferenceLinker;");
243         _getstatic4 = _class.getOrCreateStaticMethod("getstatic4", "(Ljoeq/Class/jq_StaticField;)V");
244         _getstatic8 = _class.getOrCreateStaticMethod("getstatic8", "(Ljoeq/Class/jq_StaticField;)V");
245         _putstatic4 = _class.getOrCreateStaticMethod("putstatic4", "(Ljoeq/Class/jq_StaticField;)V");
246         _putstatic8 = _class.getOrCreateStaticMethod("putstatic8", "(Ljoeq/Class/jq_StaticField;)V");
247         _getfield1 = _class.getOrCreateStaticMethod("getfield1", "(Ljoeq/Class/jq_InstanceField;)V");
248         _sgetfield = _class.getOrCreateStaticMethod("sgetfield", "(Ljoeq/Class/jq_InstanceField;)V");
249         _cgetfield = _class.getOrCreateStaticMethod("cgetfield", "(Ljoeq/Class/jq_InstanceField;)V");
250         _getfield4 = _class.getOrCreateStaticMethod("getfield4", "(Ljoeq/Class/jq_InstanceField;)V");
251         _getfield8 = _class.getOrCreateStaticMethod("getfield8", "(Ljoeq/Class/jq_InstanceField;)V");
252         _putfield1 = _class.getOrCreateStaticMethod("putfield1", "(Ljoeq/Class/jq_InstanceField;)V");
253         _putfield2 = _class.getOrCreateStaticMethod("putfield2", "(Ljoeq/Class/jq_InstanceField;)V");
254         _putfield4 = _class.getOrCreateStaticMethod("putfield4", "(Ljoeq/Class/jq_InstanceField;)V");
255         _putfield8 = _class.getOrCreateStaticMethod("putfield8", "(Ljoeq/Class/jq_InstanceField;)V");
256         _invokevirtual = _class.getOrCreateStaticMethod("invokevirtual", "(Ljoeq/Class/jq_InstanceMethod;)V");
257         _invokestatic = _class.getOrCreateStaticMethod("invokestatic", "(Ljoeq/Class/jq_Method;)V");
258         _invokespecial = _class.getOrCreateStaticMethod("invokespecial", "(Ljoeq/Class/jq_InstanceMethod;)V");
259         _invokeinterface = _class.getOrCreateStaticMethod("invokeinterface", "(Ljoeq/Class/jq_InstanceMethod;)J");
260     }
261 }